/**
 * 可以被vue观测的Set类型
 */
class MySet<T> implements Set<T>{
	constructor(iterable?:Iterable<T>){
		Object.defineProperty(this,'data',{
			value:new Set(iterable),
			enumerable:false,
			writable:true,
			configurable:true
		});
	}

	mutator(){
		// @ts-ignore
		const ob=this.__ob__;
		if(ob){
			ob.dep.notify();
		}
	}

	has(value:T):boolean{
		return (this as unknown as {data:Set<T>}).data.has(value);
	}

	// @ts-ignore
	add(value:T):MySet<T>{
		(this as unknown as {data:Set<T>}).data.add(value);
		this.mutator();
		return this;
	}

	addAll(iterable:Iterable<T>):MySet<T>{
		if(Array.isArray(iterable)){
			for(let i=0;i<iterable.length;++i){
				(this as unknown as {data:Set<T>}).data.add(iterable[i]);
			}
		}else{
			for(const value of iterable){
				(this as unknown as {data:Set<T>}).data.add(value);
			}
		}
		this.mutator();
		return this;
	}

	delete(value:T):boolean{
		const res=(this as unknown as {data:Set<T>}).data.delete(value);
		this.mutator();
		return res;
	}

	deleteAll(iterable:Iterable<T>):void{
		if(Array.isArray(iterable)){
			for(let i=0;i<iterable.length;++i){
				(this as unknown as {data:Set<T>}).data.delete(iterable[i]);
			}
		}else{
			for(const value of iterable){
				(this as unknown as {data:Set<T>}).data.delete(value);
			}
		}
		this.mutator();
	}

	clear():void{
		(this as unknown as {data:Set<T>}).data.clear();
		this.mutator();
	}

	keys():IterableIterator<T>{
		return (this as unknown as {data:Set<T>}).data.keys();
	}

	values():IterableIterator<T>{
		return (this as unknown as {data:Set<T>}).data.values();
	}

	entries():IterableIterator<[T,T]>{
		return (this as unknown as {data:Set<T>}).data.entries();
	}

	//比for of慢, 且不能中断
	forEach(callback:(value:T,key:T,set:Set<T>) => void,thisArg?:any):void{
		(this as unknown as {data:Set<T>}).data.forEach(callback,thisArg);
	}

	get size():number{
		return (this as unknown as {data:Set<T>}).data.size;
	}

	[Symbol.iterator](){
		return (this as unknown as {data:Set<T>}).data[Symbol.iterator]();
	}

	filter(predicate:(value:T,index:number) => boolean):MySet<T>{
		const res=new MySet<T>();
		const data=(this as unknown as {data:Set<T>}).data;
		let index=0;
		for(const item of data){
			if(predicate(item,index++)){
				res.add(item);
			}
		}
		return res;
	}

	filterSelf(predicate:(value:T,index:number) => boolean):void{
		const data=(this as unknown as {data:Set<T>}).data;
		let index=0;
		for(const item of data){
			if(!predicate(item,index++)){
				data.delete(item);
			}
		}
		this.mutator();
	}

	some(predicate:(value:T,index:number) => boolean):boolean{
		const data=(this as unknown as {data:Set<T>}).data;
		let index=0;
		for(const item of data){
			if(predicate(item,index++)){
				return true;
			}
		}
		return false;
	}

	every(predicate:(value:T,index:number) => boolean):boolean{
		const data=(this as unknown as {data:Set<T>}).data;
		let index=0;
		for(const item of data){
			if(!predicate(item,index++)){
				return false;
			}
		}
		return true;
	}
}
export {
	MySet,
};
